import { Color, PlaneGeometry, Mesh, ShaderMaterial, Vector3, DoubleSide, TextureLoader } from "three";
import Effect from "./Effect";
import TrailLinkShader from "../../renderExtension/Material/shaders/chunks/TrailLinkShader";
import { Point } from "../../renderExtension/types/Point";
import Const from "../../application/constants/Const";
import Events from "../../application/constants/Events";
import TrailRepeatLineShader from "../../renderExtension/Material/shaders/chunks/TrailRepeatLineShader";
import Helper from "../../utils/Helper";


/**
* 轨迹线（重复贴图）
*/
export default class TrailRepeatLine extends Effect {
    private QuadsMesh: Mesh;
    private uniforms;
    public linewidth;
    public linelength;
    public circleNum;
    public points;
    public alpha;
    public center;
    public color;
    public time;
    public texture = '../resources/images/right_arrow.png';
    private mapwidth;
    private colorObject;

    /**
    * @param cfg 配置参数
    * @config cfg.linewidth 线的宽度
    * @config cfg.textureWidth 贴图纹理的宽度
    * @config cfg.color 颜色
    * @config cfg.colorObject 颜色
    * @config cfg.points 轨迹信息
    * @config cfg.center 位置
    * @config cfg.linelength 多边形某线段长度
    * @config cfg.circleNum 重复循环次数
    * @config cfg.time 速度
    * @config cfg.displayOnTop 是否展示在最上层
   */
    constructor(cfg) {
        super();
        this.linewidth = cfg.linewidth ? cfg.linewidth : 50;
        this.mapwidth = 27;
        this.color = cfg.color;
        this.colorObject = cfg.color ? new Color(cfg.color) : new Color('ff0000');
        this.texture = cfg.texture ? cfg.texture : this.texture;
        this.points = cfg.points;
        this.points = this.changePositionEPSGType(this.points);
        this.center = [(this.points[0].x + this.points[1].x) / 2, (this.points[0].y + this.points[1].y) / 2, (this.points[0].z + this.points[1].z) / 2];
        var deltaY = this.points[1].y - this.points[0].y;
        var deltaX = this.points[1].x - this.points[0].x;
        if (Math.abs(deltaX) <= 0.00001) {
            if (deltaX > 0.0) {
                deltaX = 0.00001;
            }
            else {
                deltaX = -0.00001;
            }
        }

        if (deltaX >= 0) {
            this.alpha = Math.atan(deltaY / deltaX);
        }
        else {
            this.alpha = Math.PI + Math.atan(deltaY / deltaX);
        }
        this.linelength = Math.sqrt(deltaY * deltaY + deltaX * deltaX);
        this.circleNum = Math.ceil(this.linelength / this.mapwidth);
        this.time = cfg.time ? cfg.time : 5000;
        this.displayOnTop = cfg.displayOnTop ? cfg.displayOnTop : false;
        if (cfg.texture) {
            this.texture = cfg.texture;
        }
        this.init();
    }

    protected changePositionEPSGType(points: any) {
        let newPoints = [];
        if (points && Array.isArray(points)) {
            points.forEach(point => {
                if (point instanceof Point) {
                    let currentPoint = point.clone();
                    currentPoint.z = point.z;
                    let element = currentPoint.toEPSGWeb();
                    newPoints.push(element);
                }
            });
        }
        return newPoints;
    }

    private setUniforms() {
        var texture = new TextureLoader().load(this.texture)
        this.uniforms = {
            map: {
                value: texture
            },
            linelength: { value: this.linelength },
            linewidth: { value: this.linewidth },
            mapwidth: { value: this.mapwidth },
            v_color: { type: 'c', value: new Vector3(this.colorObject.r, this.colorObject.g, this.colorObject.b) },
            time: { type: 'f', value: 1.0 },
        };
    }

    private init() {
        let RectangleHeight = this.linewidth;
        let RectangleWidth = this.linelength;
        this.setUniforms();
        var material = new ShaderMaterial({
            uniforms: this.uniforms,
            vertexShader: TrailRepeatLineShader.getVertexShader(),
            fragmentShader: TrailRepeatLineShader.getFragmentShader(),
            side: DoubleSide,
            transparent: true,
        });

        let geo = new PlaneGeometry(RectangleWidth, RectangleHeight);
        let centerVector = new Point(this.center[0], this.center[1], this.center[2]);
        this.QuadsMesh = new Mesh(geo, material);
        this.QuadsMesh.position.set(centerVector.x, centerVector.y, centerVector.z);
        this.QuadsMesh.rotation['z'] = this.alpha;

        if (this.displayOnTop) {
            //this.QuadsMesh.material.depthTest = false;
            this.QuadsMesh.renderOrder = 99;
        }
        this.QuadsMesh.userData.isEffectMesh = true;
        this.QuadsMesh.userData.effect = this;
        this.add(this.QuadsMesh);
        this.register();
    }


    public setPosition(position) {
        this.QuadsMesh.position.set(position.x, position.y, position.z);
    }

    protected register() {
        super.register();
        this.app.on(Events.Render, this.updateUniforms, this);
    }

    public dispose() {
        this.app.off(Events.Render, this.updateUniforms, this);
        this.remove(this.QuadsMesh);
    }

    protected updateUniforms() {
        var now = new Date().getTime();
        var n = (now % this.time) / (this.time * 1.0);
        this.uniforms.time.value = n;
    }
}
